package com.gzc.just.play.client.war3server;

import com.gzc.just.play.Const;
import com.gzc.just.play.client.Client;
import com.gzc.just.play.client.ConnectionWar3ProxyServer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 为每个远程war3 game客户端创建的代理，处理TCP和UDP连接
 */
public class War3Server implements Runnable {
    private static final Logger logger = LogManager.getLogger(War3Server.class);
    
    private final String otherWar3Ip;
    private final ConnectionWar3ProxyServer connectionWar3ProxyServer;

    private volatile Future<?> tcpFuture;
    private volatile Future<?> udpFuture;

    private volatile War3UdpListener war3UdpListener;

    public War3Server(String otherWar3Ip, ConnectionWar3ProxyServer connectionWar3ProxyServer) {
        this.otherWar3Ip = otherWar3Ip;
        this.connectionWar3ProxyServer = connectionWar3ProxyServer;
    }

    public String getOtherWar3Ip() {
        return otherWar3Ip;
    }

    @Override
    public void run() {
        try {
            // 启动TCP监听器
            var tcpListener = new War3TcpListener(otherWar3Ip);
            tcpFuture = Client.executor.submit(tcpListener);

            // 启动UDP监听器
            war3UdpListener = new War3UdpListener(otherWar3Ip, connectionWar3ProxyServer);
            udpFuture = Client.executor.submit(war3UdpListener);

            // 监控TCP任务
            boolean tcpCompleted = false;
            try {
                logger.info("war3server War3TcpListener tcpFuture before get,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
                tcpFuture.get();
                tcpCompleted = true;
                logger.info("war3server War3TcpListener tcpFuture after get,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
            } catch (InterruptedException e) {
                logger.debug("TCP listener interrupted,otherWar3Ip={}", otherWar3Ip, e);
                Thread.currentThread().interrupt(); // 恢复中断状态
                if (!tcpCompleted) {
                    closeSubTasks(); // 主动关闭子任务
                }
            } catch (CancellationException e) {
                logger.info("TCP task cancelled,otherWar3Ip={}", otherWar3Ip, e);
                if (!tcpCompleted) {
                    closeSubTasks(); // 主动关闭子任务
                }
            } catch (ExecutionException e) {
                logger.error("TCP task execution error,otherWar3Ip={}", otherWar3Ip, e.getCause());
                if (!tcpCompleted) {
                    closeSubTasks(); // 异常时关闭子任务
                }
            }

            if (null == udpFuture) {
                logger.error("war3server War3UdpListener udpFuture is null,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
                return;
            }
            // 监控UDP任务
            boolean udpCompleted = false;
            try {
                logger.info("war3server War3UdpListener udpFuture before get,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
                udpFuture.get();
                udpCompleted = true;
                logger.info("war3server War3UdpListener udpFuture after get,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
            } catch (InterruptedException e) {
                logger.debug("UDP listener interrupted,otherWar3Ip={}", otherWar3Ip, e);
                Thread.currentThread().interrupt(); // 恢复中断状态
                if (!udpCompleted) {
                    closeSubTasks(); // 如果TCP任务未完成也关闭
                }
            } catch (CancellationException e) {
                logger.info("UDP task cancelled,otherWar3Ip={}", otherWar3Ip, e);
                if (!udpCompleted) {
                    closeSubTasks(); // 如果TCP任务未完成也关闭
                }
            } catch (ExecutionException e) {
                logger.error("UDP task execution error,otherWar3Ip={}", otherWar3Ip, e.getCause());
                if (!udpCompleted) {
                    closeSubTasks(); // 异常时关闭子任务
                }
            }
        } catch (Exception e) {
            logger.error("War3Server异常,otherWar3Ip={}", otherWar3Ip, e);
        } finally {
            // 确保所有资源释放
            closeSubTasks();
            removeWar3ServerFromMap();
        }
    }

    /**
     * 关闭所有子任务
     */
    private void closeSubTasks() {
        try {
            if (tcpFuture != null && !tcpFuture.isDone()) {
                logger.info("cancel tcpFuture,otherWar3Ip={}", otherWar3Ip);
                tcpFuture.cancel(true);
                tcpFuture = null;
            }
        } catch (Exception e) {
            logger.error("cancel tcpFuture error,otherWar3Ip={}", otherWar3Ip, e);
        }

        try {
            if (udpFuture != null && !udpFuture.isDone()) {
                logger.info("cancel udpFuture,otherWar3Ip={}", otherWar3Ip);
                udpFuture.cancel(true);
                udpFuture = null;
            }
        } catch (Exception e) {
            logger.error("cancel udpFuture error,otherWar3Ip={}", otherWar3Ip, e);
        }
    }

    /**
     * 从connectionMap中移除自己
     */
    private void removeWar3ServerFromMap() {
        try {
            Client.connectionMap.remove(otherWar3Ip, this);
            logger.info("Removed War3Server from map,otherWar3Ip={}", otherWar3Ip);
        } catch (Exception e) {
            logger.error("Failed to remove War3Server from map,otherWar3Ip={}", otherWar3Ip, e);
        }
    }

    public void close() {
        try {
            if (tcpFuture != null) {
                logger.info("war3server close start,tcp listen otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
                tcpFuture.cancel(true);
                tcpFuture = null;
                logger.info("war3server close ok,tcp listen otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
            }
        } catch (Exception e) {
            logger.error("war3server close tcp listen error,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT, e);
        }

        try {
            if (udpFuture != null) {
                logger.info("war3server close start,udp listen otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
                udpFuture.cancel(true);
                udpFuture = null;
                logger.info("war3server close ok,udp listen otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT);
            }
        } catch (Exception e) {
            logger.error("war3server close udp listen error,otherWar3Ip={},port={}", otherWar3Ip, Const.WAR3_PORT, e);
        }
    }

    public void udpSend(byte[] data) {
        if (war3UdpListener != null) {
            logger.info("war3UdpListener send data,otherWar3Ip={},data={}", otherWar3Ip, data);
            war3UdpListener.send(data);
        } else {
            logger.error("war3UdpListener is null,can not send data,otherWar3Ip={}", otherWar3Ip);
        }
    }
}
